package utility.math;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlType;

/**
 * @author tioz
 *
 */

@XmlType (
	    name = "##default", 
	    propOrder = {""}, 
	    namespace = "##default" 
	    //factoryClass = DEFAULT.class, 
	    //factoryMethod = ""
	)

public class Vector2D implements Serializable,Cloneable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 6440237858328119412L;
	double x,y;
	
	
	
	public Vector2D(){
		this.x = 0;
		this.y = 0;
	}
	
	public Vector2D(double x,double y){
		this.x = x;
		this.y = y;
	}


	/**
	 * @param vector2d
	 */
	public Vector2D(Vector2D v) {
		x=v.x;
		y=v.y;
	}


	/**
	 * @param vec second vector
	 * @return the scalar product
	 */
	public double dotProduct(Vector2D vec){
		return vec.getX() * getX() + vec.getY() * getY();	
	}
	
	/**
	 * @param vec second vector in the cross product
	 * @return the z component of the cross product
	 */
	public double crossProduct(Vector2D vec){
		return getX() * vec.getY() - getY() * vec.getX();
	}
	
		
	
	public Vector2D minus(Vector2D v2){
		return new Vector2D(x-v2.x,y-v2.y);
	}

	public void thisMinus(Vector2D v2){
		x=x-v2.x;
		y=y-v2.y;
	}
	
	public Vector2D plus(Vector2D v2){
		return new Vector2D(x+v2.x,y+v2.y);
	}
	
	public void thisPlus(Vector2D c) {
		x+=c.x;
		y+=c.y;
	}
	
	
	public void thisTime(double number){
		x= number*x;
		y= number*y;
	}

	public double norm(){
		return Math.sqrt(x*x+y*y);
	}
	
	public double normSquared(){
		return x*x+y*y;
	}
	
	public double getAngle(Vector2D vec){
		return Math.acos(this.dotProduct(vec)/(this.norm()*vec.norm()));
	}
	
	
	public double getX() {
		return x;
	}



	public void setX(double x) {
		this.x = x;
	}



	public double getY() {
		return y;
	}



	public void setY(double y) {
		this.y = y;
	}





	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		long temp;
		temp = Double.doubleToLongBits(x);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		temp = Double.doubleToLongBits(y);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}


	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Vector2D other = (Vector2D) obj;
		if (Double.doubleToLongBits(x) != Double.doubleToLongBits(other.x))
			return false;
		if (Double.doubleToLongBits(y) != Double.doubleToLongBits(other.y))
			return false;
		return true;
	}


	/**
	 * @param h
	 * @return
	 */
	public Vector2D time(double h) {
		return new Vector2D(x*h,y*h);
	}
	
	
	public Object clone(){
			Object o = null;
			try
			{
				o = super.clone();
			}
			catch(CloneNotSupportedException ex)
			{
				ex.printStackTrace(System.err);
			}
			return o;
	}

	/**
	 * @param plus
	 */
	public void set(Vector2D v) {
		x = v.x;
		y = v.y; 		
	}

	public static Vector2D plus(Vector2D a, Vector2D b, Vector2D result){
		result.x= a.x + b.x;
		result.y= a.x + b.x;
		return result;
	}
		
	public static Vector2D minus(Vector2D a, Vector2D b, Vector2D result){
		result.x= a.x - b.x;
		result.y= a.x - b.x;
		return result;
	}

	public static Vector2D time(double k,Vector2D a, Vector2D result){
		result.x= k*a.x;
		result.y= k*a.x;
		return result;
	}

	/**
	 * @return Displayable string
	 */
	public String display() {
		return "X: "+x +"  Y: "+y;
	}
	
	
}
